/*
 * Partida.cpp
 *
 *  Created on: 28/06/2014
 *      Author: loreyalan
 */

#include "Partida.h"

Partida *Partida::instance = NULL;

/* Mapa de comandos */
map<int, ComandoServidor *> mapaComandos;

/* Funciones */

/* Convierte un idimagen de numero en una constante */
unsigned int Partida::obtenerNumero(unsigned char letra)
{

    switch (letra)
                {
                 case CERO:  return CONST_CERO; break;
                 case UNO:  return CONST_UNO; break;
                 case DOS:  return CONST_DOS; break;
                 case TRES:  return CONST_TRES; break;
                 case CUATRO:  return CONST_CUATRO; break;
                 case CINCO:  return CONST_CINCO; break;
                 case SEIS:  return CONST_SEIS; break;
                 case SIETE:  return CONST_SIETE; break;
                 case OCHO:  return CONST_OCHO; break;
                 case NUEVE:  return CONST_NUEVE; break;
                }
    return VACIO;
}

/* Obtengo el numero de nivel actual*/
unsigned int Partida::obtenerNivel(){
    unsigned int nivel;
    //Niveles del 1 al 99
    nivel = obtenerNumero(matriz[52][0].nombre)*10 + obtenerNumero(matriz[52][1].nombre);
    return nivel;
}

//// Convierte String a mayusculas ////////////////////////////////////////////
string upcase(string s1){
  string tmp=s1;
  for (unsigned short int i=0; i < s1.size(); i++)
     tmp.at(i) = toupper(tmp.at(i));
  return tmp;
}

///// Corrijo los caracteres del nombre (solo letras y mayusculas) ////////////////////
string corregirNombre(string nombre){
	string correctos="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	string aux="";

	for (unsigned short int j=0;j<=9;j++) //maximo 10 caracteres
		for (unsigned short int i=0;i<correctos.size();i++)
			if(nombre[j]==correctos[i])
				aux+=nombre[j];

	//Convierto a mayusculas
	string nombreMayuscula;
	nombreMayuscula=upcase(aux);

	return nombreMayuscula;
}

// A partir de un char te devuelve el id_image del caracter */
unsigned char obtenerIdCaracter(unsigned short int jugador,char letra)
{
switch (jugador)
      {
       case 1:
       	 switch (letra)
       	        {
       	         case 'A':  return A1; break;
       	         case 'B':  return B1; break;
       	         case 'C':  return C1; break;
       	         case 'D':  return D1; break;
       	         case 'E':  return E1; break;
       	         case 'F':  return F1; break;
       	         case 'G':  return G1; break;
       	         case 'H':  return H1; break;
       	         case 'I':  return I1; break;
       	         case 'J':  return J1; break;
       	         case 'K':  return K1; break;
       	         case 'L':  return L1; break;
       	         case 'M':  return M1; break;
       	         case 'N':  return N1; break;
                 case 'O':  return O1; break;
       	         case 'P':  return P1; break;
       	         case 'Q':  return Q1; break;
       	         case 'R':  return R1; break;
       	         case 'S':  return S1; break;
       	         case 'T':  return T1; break;
       	         case 'U':  return U1; break;
       	         case 'V':  return V1; break;
       	         case 'W':  return W1; break;
       	         case 'X':  return X1; break;
       	         case 'Y':  return Y1; break;
       	         case 'Z':  return Z1; break;
       	        }
              break;
       	 case 2:
       	 switch (letra)
       	 {
       	 case 'A':  return A2; break;
       	 case 'B':  return B2; break;
       	 case 'C':  return C2; break;
       	 case 'D':  return D2; break;
       	 case 'E':  return E2; break;
       	 case 'F':  return F2; break;
       	 case 'G':  return G2; break;
       	 case 'H':  return H2; break;
       	 case 'I':  return I2; break;
       	 case 'J':  return J2; break;
       	 case 'K':  return K2; break;
       	 case 'L':  return L2; break;
       	 case 'M':  return M2; break;
       	 case 'N':  return N2; break;
       	 case 'O':  return O2; break;
       	 case 'P':  return P2; break;
       	 case 'Q':  return Q2; break;
       	 case 'R':  return R2; break;
       	 case 'S':  return S2; break;
       	 case 'T':  return T2; break;
       	 case 'U':  return U2; break;
       	 case 'V':  return V2; break;
       	 case 'W':  return W2; break;
       	 case 'X':  return X2; break;
       	 case 'Y':  return Y2; break;
       	 case 'Z':  return Z2; break;
       	        }
              break;

      }

switch (letra)
       	        {
       	         case '0':  return CERO; break;
       	         case '1':  return UNO; break;
       	         case '2':  return DOS; break;
       	         case '3':  return TRES; break;
       	         case '4':  return CUATRO; break;
       	         case '5':  return CINCO; break;
       	         case '6':  return SEIS; break;
       	         case '7':  return SIETE; break;
       	         case '8':  return OCHO; break;
       	         case '9':  return NUEVE; break;
       	        }
return VACIO;
}

/* A partir de un numero te devuelve el id_image */
unsigned char obtenerIdNumero(unsigned short int numero){
	switch (numero)
	       	        {
	       	         case 0:  return CERO; break;
	       	         case 1:  return UNO; break;
	       	         case 2:  return DOS; break;
	       	         case 3:  return TRES; break;
	       	         case 4:  return CUATRO; break;
	       	         case 5:  return CINCO; break;
	       	         case 6:  return SEIS; break;
	       	         case 7:  return SIETE; break;
	       	         case 8:  return OCHO; break;
	       	         case 9:  return NUEVE; break;
	       	        }
	return VACIO;
}


// Cargo el puntaje del Jugador en la matriz //////////////////////////
void Partida::cargarPuntaje(string punt, unsigned short int jugador){
	if(jugador==JUGADOR1){//Jugador 1
		for (unsigned short int j=0;j<7;j++) //maximo 7 digitos
			matriz[45][j].nombre=obtenerIdCaracter(1,punt[j]);
		for(unsigned short int j=0; j<7;j+=1){
			matriz[45][j].destino.x= 114+17*j;
			matriz[45][j].destino.y=60;
		}
	}else{ //Jugador 2
	 for (unsigned short int j=0;j<7;j++) //maximo 7 digitos
	   matriz[47][j].nombre=obtenerIdCaracter(2,punt[j]);
	 for(unsigned short int j=0; j<7;j+=1){
		matriz[47][j].destino.x= 570+17*j;
		matriz[47][j].destino.y=60;
	  }
	}
}

// Cargo las vidas del Jugador en la matriz //////////////////////////
void Partida::cargarVidas(unsigned char vidas, unsigned short int jugador){
	if(jugador==JUGADOR1){//Jugador 1
		matriz[48][0].nombre=vidas;
		matriz[48][0].destino.x= 318;
		matriz[48][0].destino.y=39;
	}else {//Jugador 2
		matriz[49][0].nombre=vidas;
		matriz[49][0].destino.x= 516;
		matriz[49][0].destino.y=39;
	}
}


// Dado un IdEntidad y el tramo actual del nivel devuelve la coordenada x(fila) y(columna)
// en donde se encuentra dentro de la matriz de entidades
SDL_Rect idEntidadToXy(unsigned short int id_entidad, unsigned short int tramo)
{
SDL_Rect coordenada;
 switch (id_entidad)
    {
     case ID_VIDRIO0:  coordenada.x=40-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO1:  coordenada.x=40-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO2:  coordenada.x=40-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO3:  coordenada.x=40-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO4:  coordenada.x=40-(tramo-1)*9; coordenada.y=8; break;
     case ID_VIDRIO5:  coordenada.x=39-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO6:  coordenada.x=39-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO7:  coordenada.x=39-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO8:  coordenada.x=39-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO9:  coordenada.x=39-(tramo-1)*9; coordenada.y=8; break;
     case ID_VIDRIO10: coordenada.x=37-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO11: coordenada.x=37-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO12: coordenada.x=37-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO13: coordenada.x=37-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO14: coordenada.x=37-(tramo-1)*9; coordenada.y=8; break;
     case ID_VIDRIO15: coordenada.x=36-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO16: coordenada.x=36-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO17: coordenada.x=36-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO18: coordenada.x=36-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO19: coordenada.x=36-(tramo-1)*9; coordenada.y=8; break;
     case ID_VIDRIO20: coordenada.x=34-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO21: coordenada.x=34-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO22: coordenada.x=34-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO23: coordenada.x=34-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO24: coordenada.x=34-(tramo-1)*9; coordenada.y=8; break;
     case ID_VIDRIO25: coordenada.x=33-(tramo-1)*9; coordenada.y=0; break;
     case ID_VIDRIO26: coordenada.x=33-(tramo-1)*9; coordenada.y=2; break;
     case ID_VIDRIO27: coordenada.x=33-(tramo-1)*9; coordenada.y=4; break;
     case ID_VIDRIO28: coordenada.x=33-(tramo-1)*9; coordenada.y=6; break;
     case ID_VIDRIO29: coordenada.x=33-(tramo-1)*9; coordenada.y=8; break;

     case ID_BLOQUEO0:  coordenada.x=39-(tramo-1)*9; coordenada.y=1; break;
     case ID_BLOQUEO1:  coordenada.x=39-(tramo-1)*9; coordenada.y=3; break;
     case ID_BLOQUEO2:  coordenada.x=39-(tramo-1)*9; coordenada.y=5; break;
     case ID_BLOQUEO3:  coordenada.x=39-(tramo-1)*9; coordenada.y=7; break;
     case ID_BLOQUEO4:  coordenada.x=38-(tramo-1)*9; coordenada.y=0; break;
     case ID_BLOQUEO5:  coordenada.x=38-(tramo-1)*9; coordenada.y=2; break;
     case ID_BLOQUEO6:  coordenada.x=38-(tramo-1)*9; coordenada.y=4; break;
     case ID_BLOQUEO7:  coordenada.x=38-(tramo-1)*9; coordenada.y=6; break;
     case ID_BLOQUEO8:  coordenada.x=38-(tramo-1)*9; coordenada.y=8; break;
     case ID_BLOQUEO9:  coordenada.x=36-(tramo-1)*9; coordenada.y=1; break;
     case ID_BLOQUEO10: coordenada.x=36-(tramo-1)*9; coordenada.y=3; break;
     case ID_BLOQUEO11: coordenada.x=36-(tramo-1)*9; coordenada.y=5; break;
     case ID_BLOQUEO12: coordenada.x=36-(tramo-1)*9; coordenada.y=7; break;
     case ID_BLOQUEO13: coordenada.x=35-(tramo-1)*9; coordenada.y=0; break;
     case ID_BLOQUEO14: coordenada.x=35-(tramo-1)*9; coordenada.y=2; break;
     case ID_BLOQUEO15: coordenada.x=35-(tramo-1)*9; coordenada.y=4; break;
     case ID_BLOQUEO16: coordenada.x=35-(tramo-1)*9; coordenada.y=6; break;
     case ID_BLOQUEO17: coordenada.x=35-(tramo-1)*9; coordenada.y=8; break;
     case ID_BLOQUEO18: coordenada.x=33-(tramo-1)*9; coordenada.y=1; break;
     case ID_BLOQUEO19: coordenada.x=33-(tramo-1)*9; coordenada.y=3; break;
     case ID_BLOQUEO20: coordenada.x=33-(tramo-1)*9; coordenada.y=5; break;
     case ID_BLOQUEO21: coordenada.x=33-(tramo-1)*9; coordenada.y=7; break;

     case ID_RALPH:     coordenada.x=43; coordenada.y=2; break;
     case ID_FELIX1:    coordenada.x=43; coordenada.y=0; break;
     case ID_FELIX2:    coordenada.x=43; coordenada.y=1; break;
     case ID_PALOMA:    coordenada.x=43; coordenada.y=4; break;
     case ID_TORTA:     coordenada.x=43; coordenada.y=3; break;
     case ID_LADRILLO0: coordenada.x=43; coordenada.y=5; break;
     case ID_LADRILLO1: coordenada.x=43; coordenada.y=6; break;
     case ID_LADRILLO2: coordenada.x=43; coordenada.y=7; break;
     case ID_LADRILLO3: coordenada.x=43; coordenada.y=8; break;
     case ID_LADRILLO4: coordenada.x=43; coordenada.y=9; break;

    }
return coordenada;
}


/* Convierte a char constantes */
char obtenerCaracter(unsigned char idCaracter){
 switch (idCaracter)
    {
     case CERO:   return '0'; break;
     case UNO:    return '1'; break;
     case DOS:    return '2'; break;
     case TRES:   return '3'; break;
     case CUATRO: return '4'; break;
     case CINCO:  return '5'; break;
     case SEIS:   return '6'; break;
     case SIETE:  return '7'; break;
     case OCHO:   return '8'; break;
     case NUEVE:  return '9'; break;
    }
 return '0';
}

// Obtengo el puntaje del jugador ////////////////////////////
string Partida::obtenerPuntaje(unsigned short int jugador){
	string puntaje="";

	if(jugador==JUGADOR1){//Jugador 1
	 for (unsigned short int j=0;j<7;j++)
		 puntaje+=obtenerCaracter(matriz[45][j].nombre);

	}
	else{ //Jugador 2
	 for (unsigned short int j=0;j<7;j++)
		 puntaje+=obtenerCaracter(matriz[47][j].nombre);
	}

	return puntaje;
}

// Incremento el puntaje del jugador ///////////////////////////
void incrementarPuntaje(string *puntaje, unsigned char puntajeVidrioReparado){
	unsigned short int bonus=puntajeVidrioReparado;
	int p;
	string aux=*puntaje;
	p=atoi(aux.c_str())+bonus;

	stringstream stream;
	stream << p;
	aux = stream.str();

	string aux2="";
	for(unsigned short int i=0;i<(7-aux.size());i++)
	  aux2+="0";
	aux2+=aux;

	*puntaje=aux2;
}
////////// Devuelve la coordenada de un sprite dentro de la imagen //////////////////////
SDL_Rect Partida::obtenerOrigenSprite(unsigned char nombre)
{
 SDL_Rect origen;
switch(nombre)
{
case	VIDRIO_SANO :	origen.x = 608; origen.y = 0; origen.w = 25; origen.h = 21; break;
case	VIDRIO_ROTO1 :	origen.x = 608; origen.y = 64; origen.w = 25; origen.h = 21; break;
case	VIDRIO_ROTO2 :	origen.x = 608; origen.y = 32; origen.w = 25; origen.h = 21; break;
case	VIDRIO_ROTO3 :	origen.x = 640; origen.y = 32; origen.w = 25; origen.h = 21; break;
case	VIDRIO_ROTO4 :	origen.x = 640; origen.y = 64; origen.w = 25; origen.h = 21; break;
case	PASTO :	 		origen.x = 1024; origen.y = 1496; origen.w = 581; origen.h = 25; break;
case	EDIF_PLNT_BAJA: origen.x = 14; origen.y = 1; origen.w = 421; origen.h = 439; break;
case	EDIF_TRAMO :	origen.x = 1413; origen.y = 224; origen.w = 421; origen.h = 435; break;
case	EDIF_AZOTEA :	origen.x = 590; origen.y = 1608; origen.w = 421; origen.h = 313; break;
case	VENT_CENT :		origen.x = 456; origen.y = 104; origen.w = 81; origen.h = 73; break;
case	VENT_CENT_ROTA: origen.x = 552; origen.y = 104; origen.w = 81; origen.h = 73; break;
case	PUERTA :		origen.x = 650; origen.y = 96; origen.w = 79; origen.h = 128; break;
case	PUERTA_ROTA1 :	origen.x = 746; origen.y = 96; origen.w = 79; origen.h = 128; break;
case	PUERTA_ROTA2 :	origen.x = 842; origen.y = 96; origen.w = 79; origen.h = 128; break;
case	PUERTA_ROTA3 :	origen.x = 938; origen.y = 96; origen.w = 79; origen.h = 128; break;
case	MACETA :		origen.x = 452; origen.y = 190; origen.w = 82; origen.h = 31;  break;
case	BARRA_SUP :		origen.x = 1035; origen.y = 1956; origen.w = 581; origen.h = 4;  break;
case	PANEL_SUP :		origen.x = 1005; origen.y = 1227; origen.w = 800; origen.h = 90; break;
case	BANDA_NEGRA :	origen.x = 1005; origen.y = 1168; origen.w = 800; origen.h = 90;  break;
case	BARRA_INF :		origen.x = 1035; origen.y = 1963; origen.w = 581; origen.h = 4;  break;
case	BLOQ_ARR :		origen.x = 1840; origen.y = 0; origen.w = 51; origen.h = 13; break;
case	BLOQ_DER :		origen.x = 1984; origen.y = 11; origen.w = 9; origen.h = 69; break;
case	TORTA1 :		origen.x = 800; origen.y = 6; origen.w = 23; origen.h = 27; break;
case	TORTA2 :		origen.x = 832; origen.y = 6; origen.w = 23; origen.h = 27; break;
case	LADRILLO1 :		origen.x = 736; origen.y = 0; origen.w = 25; origen.h = 17; break;
case	LADRILLO2 :		origen.x = 770; origen.y = 0; origen.w = 25; origen.h = 17; break;
case	FELIX1 :		origen.x = 4; origen.y = 446; origen.w = 31; origen.h = 83; break;
case	FELIX2 :		origen.x = 4; origen.y = 446; origen.w = 31; origen.h = 83; break;
case	RALPH :	 		origen.x = 22; origen.y = 852; origen.w = 91; origen.h = 109; break;
case	PALOMA1 :	 	origen.x = 870; origen.y = 320; origen.w = 43; origen.h = 39; break;
case	PALOMA2 :	 	origen.x = 918; origen.y = 320; origen.w = 43; origen.h = 39; break;
case	CERO :	 		origen.x = 256; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	UNO :	  		origen.x = 274; origen.y = 1936; origen.w = 13; origen.h = 15; break;
case	DOS :			origen.x = 288; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	TRES :	 		origen.x = 304; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	CUATRO :		origen.x = 320; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	CINCO :			origen.x = 336; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	SEIS :			origen.x = 352; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	SIETE :			origen.x = 368; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	OCHO :			origen.x = 384; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	NUEVE :	 		origen.x = 400; origen.y = 1936; origen.w = 15; origen.h = 15; break;
case	A1 :	 		origen.x = 528; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	B1 :			origen.x = 544; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	C1 :			origen.x = 560; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	D1 :			origen.x = 576; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	E1 :			origen.x = 592; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	F1 :			origen.x = 608; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	G1 :			origen.x = 624; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	H1 :	 		origen.x = 640; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	I1 :			origen.x = 658; origen.y = 1984; origen.w = 13; origen.h = 15; break;
case	J1 :			origen.x = 672; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	K1 :	 		origen.x = 688; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	L1 :			origen.x = 704; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	M1 :			origen.x = 720; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	N1 :			origen.x = 736; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	O1 :	 		origen.x = 752; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	P1 :			origen.x = 768; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	Q1 :	 		origen.x = 784; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	R1 :	 		origen.x = 800; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	S1 :	 		origen.x = 816; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	T1 :	 		origen.x = 834; origen.y = 1984; origen.w = 13; origen.h = 15; break;
case	U1 :	 		origen.x = 848; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	V1 :	 		origen.x = 864; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	W1 :	 		origen.x = 880; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	X1 :	 		origen.x = 896; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	Y1 :	 		origen.x = 914; origen.y = 1984; origen.w = 13; origen.h = 15; break;
case	Z1 :	 		origen.x = 928; origen.y = 1984; origen.w = 15; origen.h = 15; break;
case	A2 :	 		origen.x = 528; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	B2 :	 		origen.x = 256; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	C2 :	 		origen.x = 560; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	D2 :			origen.x = 576; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	E2 :	 		origen.x = 592; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	F2 :	 		origen.x = 608; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	G2 :	 		origen.x = 624; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	H2 :	 		origen.x = 640; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	I2 :	 		origen.x = 658; origen.y = 2000; origen.w = 13; origen.h = 15; break;
case	J2 :	 		origen.x = 672; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	K2 :	 		origen.x = 688; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	L2 :	 		origen.x = 704; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	M2 :	 		origen.x = 720; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	N2 :	 		origen.x = 736; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	O2 :	 		origen.x = 752; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	P2 :	 		origen.x = 768; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	Q2 :	 		origen.x = 784; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	R2 :	 		origen.x = 800; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	S2 :	 		origen.x = 816; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	T2 :	 		origen.x = 834; origen.y = 2000; origen.w = 13; origen.h = 15; break;
case	U2 :	 		origen.x = 848; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	V2 :	 		origen.x = 864; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	W2 :	 		origen.x = 880; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	X2 :	 		origen.x = 896; origen.y = 2000; origen.w = 15; origen.h = 15; break;
case	Y2 :	 		origen.x = 914; origen.y = 2000; origen.w = 13; origen.h = 15; break;
case	Z2 :	 		origen.x = 928; origen.y = 2000; origen.w = 15; origen.h = 15; break;

}
 return origen;
}


Partida::Partida() {
	/* Mutex */
	mutexPantalla = new ThreadMutex();
	mutexColaAccionesAEjecutar= new ThreadMutex();
	mutexColaAccionesAEnviar= new ThreadMutex();
	mutexHayQueEjecutar= new ThreadMutex();
	mutexHayQueEnviar= new ThreadMutex();

	/* Comandos */
	mapaComandos[ACC_MOVER] 	   			= (ComandoServidor *) new ComandoMover();
	mapaComandos[ACC_CREAR_AVE]  			= (ComandoServidor *) new ComandoCrearAve();
	mapaComandos[ACC_CREAR_LADRILLO]		= (ComandoServidor *) new ComandoCrearLadrillo();
	mapaComandos[ACC_CREAR_TORTA]			= (ComandoServidor *) new ComandoCrearTorta();
	mapaComandos[ACC_REPARAR] 	   		= (ComandoServidor *) new ComandoReparar();
	mapaComandos[ACC_DELETE_AVE] 			= (ComandoServidor *) new ComandoDeleteAve();
	mapaComandos[ACC_DELETE_LADRILLO] 	= (ComandoServidor *) new ComandoDeleteLadrillo();
	mapaComandos[ACC_DELETE_TORTA]		= (ComandoServidor *) new ComandoDeleteTorta();
	mapaComandos[ACC_LANZAR_LADRILLO]		= (ComandoServidor *) new ComandoLanzarLadrillo();
	mapaComandos[ACC_FIN_TRAMO]			= (ComandoServidor *) new ComandoFinTramo();
	mapaComandos[ACC_FIN_NIVEL]			= (ComandoServidor *) new ComandoFinNivel();
	mapaComandos[ACC_FIN_PARTIDA]			= (ComandoServidor *) new ComandoFinPartida();
	mapaComandos[ACC_INIT_PARTIDA]		= (ComandoServidor *) new ComandoInitPartida();
	mapaComandos[ACC_INIT_NIVEL]			= (ComandoServidor *) new ComandoInitNivel();
	mapaComandos[ACC_INIT_TRAMO]			= (ComandoServidor *) new ComandoInitTramo();
	mapaComandos[ACC_ACT_RANK]			= (ComandoServidor *) new ComandoActRanking();
	mapaComandos[ACC_COMENZAR]			= (ComandoServidor *) new ComandoComenzar();
	mapaComandos[ACC_ACT_PUNT]			= (ComandoServidor *) new ComandoActualizarPuntaje();

	/* Arrancan tomados */
	mutexHayQueEnviar->P();
	mutexHayQueEjecutar->P();

	tramo = CONST_UNO;
	stoped = CONST_TRUE;
	miIdJugador   =CONST_UNO;
	estoyVivo     =CONST_TRUE; //TODO: VER esto.

}

Partida::~Partida() {
	// TODO Auto-generated destructor stub
}

/*Retorna la instancia si existe, sino la crea y la retorna.*/
Partida *Partida::getInstance(){
	if(!instance)
		instance = new Partida();

	return instance;
}

/* Getters */
bool Partida::isActivo(){
	return instance->activo;
}

bool Partida::isStoped(){
	return instance->stoped;
}

/* Setters */
void Partida::setMiNombre(string miNombre){
	instance->miNombre = miNombre;
}

void Partida::setControles(map<int, int> *controles){
	instance->controles = controles;
}

void Partida::setPantallaBase(SDL_Surface *pantallaBase){
	instance->pantallaBase = pantallaBase;
}

void Partida::setImagen1(SDL_Surface *imagen1){
	instance->imagen1 = imagen1;
}

void Partida::setImagen2(SDL_Surface *imagen2){
	instance->imagen2 = imagen2;
}

/* Agrega la t_accion recibida por parámetro, a la cola de acciones a ejecutar. */
void Partida::encolarAccionAEjecutar(t_accion action){
	bool liberar;

	if(instance->colaAccionesAEjecutar.empty())
		liberar = CONST_TRUE;

	//Encolo la t_accion.
	instance->mutexColaAccionesAEjecutar->P();
	instance->colaAccionesAEjecutar.push(action);
	instance->mutexColaAccionesAEjecutar->V();

	//Si es el primero que cargo, libero el mutex. d
	if(liberar)
		instance->mutexHayQueEjecutar->V();
}

/* Va sacando de la cola de acciones, para ejecutarlas. */
t_accion Partida::desencolarAccionAEjecutar(){
	t_accion a;

	//Espero a que halla acciones encoladas.
	instance->mutexHayQueEjecutar->P();

	//Cuando hay, desencolo.
	instance->mutexColaAccionesAEjecutar->P();
	a = instance->colaAccionesAEjecutar.front();
	instance->colaAccionesAEjecutar.pop();
	instance->mutexColaAccionesAEjecutar->V();

	//Si no quedan mas datos, lo dejo tomado hasta que el que carge la cola lo libere.
	if(!instance->colaAccionesAEjecutar.empty())
		instance->mutexHayQueEjecutar->V();

	return a;
}

/* Agrega la t_accion recibida por parámetro, a la cola de acciones a ejecutar. */
void Partida::encolarAccionAEnviar(t_accion action){
	bool liberar;
	if(instance->colaAccionesAEnviar.empty())
		liberar = CONST_TRUE;

	//Encolo la t_accion.
	instance->mutexColaAccionesAEnviar->P();
	instance->colaAccionesAEnviar.push(action);
	instance->mutexColaAccionesAEnviar->V();

	//Si es el primero que cargo, libero el mutex. d
	if(liberar)
		instance->mutexHayQueEnviar->V();
}

/* Va sacando de la cola de acciones, para ejecutarlas. */
t_accion Partida::desencolarAccionAEnviar(){
	t_accion a;

	//Espero a que halla acciones encoladas.
	instance->mutexHayQueEnviar->P();

	//Cuando hay, desencolo.
	instance->mutexColaAccionesAEnviar->P();
	a = instance->colaAccionesAEnviar.front();
	instance->colaAccionesAEnviar.pop();
	instance->mutexColaAccionesAEnviar->V();

	//Si no quedan mas datos, lo dejo tomado hasta que el que carge la cola lo libere.
	if(!instance->colaAccionesAEnviar.empty())
		instance->mutexHayQueEnviar->V();

	return a;
}

/* Desencola una accion a ejecutar, y la ejecuta impactando en la matriz de display */
void Partida::procesarAccion(){
    t_accion action = desencolarAccionAEjecutar();
    ComandoServidor *cS = mapaComandos[action.id_accion];
	cS->execute(&action);
}

/* Funcion que toma el proximo ingreso de tecla y lo encola para ser enviado al servidor.*/
void Partida::tomarAccionPresionada(){
	/* Se queda bloqueado esperando la tecla */
	t_accion action = instance->getTeclaPresionada();

	if(action.id_entidad != CONST_MAX_UINT)
		/* Encolo la accion de la tecla presionada */
		instance->encolarAccionAEnviar(action);
}

/* Funcionalidades */

/* Recibe las teclas ingresadas por el jugador y genera las acciones a encolar pertinenetes */
t_accion Partida::getTeclaPresionada(){
	//TODO: Acciones SDL_Key
	t_accion accion;
	accion.id_entidad = CONST_MAX_UINT;
	SDL_Event event;
	SDL_WaitEvent(&event); //Se bloquea esperando un evento

	switch(event.type){
	case SDL_QUIT:
		accion.id_accion = ACC_SALIR_JUEGO;
		accion.id_entidad= instance->miIdJugador;
		break;

	case SDL_KEYDOWN:
	   accion = procesarEventoSDLKeyDown(&event);
	   break;
	}

	return accion;
}

/* Metodo que interpreta el evento SDL_Event de teclado */
t_accion Partida::procesarEventoSDLKeyDown(SDL_Event *event) {
	t_accion accion;
	accion.id_entidad = CONST_MAX_UINT;

	/* Si presiono escape, ejecuta la accion salir del juego */
	if(event->key.keysym.sym == SDLK_ESCAPE){
		//Salir torneo
		accion.id_accion  = ACC_SALIR_JUEGO;
		accion.id_entidad = instance->miIdJugador;
		return accion;

	}else if(estoyVivo == CONST_TRUE){
		/* Analizao la tecla presionada */
		switch( (*controles)[event->key.keysym.sym] ){
		case UP:
			/* Envio la accion se moverse para arriba */
			accion.id_accion	= ACC_MOVER;
			accion.id_entidad	= miIdJugador;
			accion.mov_x	 	= CONST_CERO;
			accion.mov_y	 	= CONST_MENOS_UNO * ANCHO_MOV_Y_FELIX;
			break;

		case DOWN:
			/* Envio la accion se moverse para abajo */
			accion.id_accion	= ACC_MOVER;
			accion.id_entidad	= miIdJugador;
			accion.mov_x	 	= CONST_CERO;
			accion.mov_y	 	= ANCHO_MOV_Y_FELIX;
			break;

		case RIGHT:
			/* Envio la accion para moverse a la derecha */
			accion.id_accion	= ACC_MOVER;
			accion.id_entidad	= miIdJugador;
			accion.mov_x		= ANCHO_MOV_X_FELIX;
			accion.mov_y		= CONST_CERO;
			break;

		case LEFT:
			/* Envio la accion para moverse a la derecha */
			accion.id_accion	= ACC_MOVER;
			accion.id_entidad	= miIdJugador;
			accion.mov_x		= CONST_MENOS_UNO * ANCHO_MOV_X_FELIX;
			accion.mov_y		= CONST_CERO;
			break;

		case REPARAR:

			//Simulo recibir la accion ACC_REPARAR del Servidor de Partida
			accion.id_accion	= ACC_REPARAR;
			accion.id_entidad	= miIdJugador;
			accion.mov_x		= CONST_CERO;
			accion.mov_y		= CONST_CERO;
		}
	}

	return accion;
}

/* Funcion que ejecuta la actualizacion de la informacion en la pantalla */
void Partida::refreshDisplay(){
	/* Tomo el mutex */
	mutexPantalla->P();

	//TODO: Optimizar!
	//Borro pantalla
	  SDL_Rect PosScr;
	  PosScr.x = 0;
	  PosScr.y = 0;
	  PosScr.w = pantallaBase -> w;
	  PosScr.h = pantallaBase -> h;
	  SDL_FillRect( pantallaBase, &PosScr, SDL_MapRGB( pantallaBase -> format, 0, 0, 0) );

	//Dibujo matriz
	SDL_Rect aux,aux2;
	for(int i=0; i<=52;i++)
	for(int j=0;j<=9;j++)
	  if(matriz[i][j].nombre!=VACIO)
	     {
	     aux=obtenerOrigenSprite(matriz[i][j].nombre);
	     aux2=matriz[i][j].destino;
	     if(matriz[i][j].nombre==FELIX2)
	      SDL_BlitSurface(imagen2, &aux, pantallaBase, &aux2);
	     else
	      SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	     }
	/*    SDL_Rect aux,aux2;
	    SDL_Rect coordenada;

	    for(unsigned short int j=0; j<8; j++){
	  	  aux=obtenerOrigenSprite(matriz[0][j].nombre);
	  	  aux2=matriz[0][j].destino;
	  	  SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    }

	    	    //Dibujo: Vidrios
	    		for(unsigned short int idVidrio=ID_VIDRIO_INI; idVidrio<ID_VIDRIO_CANT; idVidrio++){

	    			//Me posiciono en el vidrio seleccionado sobre la matriz.
	    			coordenada=idEntidadToXy(idVidrio, tramo);
	    			if(matriz[coordenada.x][coordenada.y].nombre!=VACIO)
	    			  			{
	    		     aux=obtenerOrigenSprite(matriz[coordenada.x][coordenada.y].nombre);
	    		     aux2=matriz[coordenada.x][coordenada.y].destino;
	    		     SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    			  			}

	    		}
	    	    //Dibujo: Bloqueos
	    		for(unsigned short int idBloqueo=ID_BLOQUEO_INI; idBloqueo<=MAX_IDX_BLOQUEOS; idBloqueo++){

	    			//Me posiciono en el vidrio seleccionado sobre la matriz.
	    			coordenada=idEntidadToXy(idBloqueo, tramo);
	    			//cout<<"Error"<<endl;
	    			if(matriz[coordenada.x][coordenada.y].nombre!=VACIO)
	    			{
	    			switch(matriz[coordenada.x][coordenada.y].nombre)
	    			{
	    			case	BLOQ_ARR :	aux.x = 1840; aux.y = 0; aux.w = 51; aux.h = 13; break;
	    			case	BLOQ_DER :	aux.x = 1984; aux.y = 11; aux.w = 9; aux.h = 69; break;
	    			}
	    		    // aux=obtenerOrigenSprite(m[coordenada.x][coordenada.y].nombre);
	    		     aux2=matriz[coordenada.x][coordenada.y].destino;
	               SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    			}
	    		}

	    		//Dibujo: Panel superior y bandas que cubren arriba y abajo
	    			for(unsigned short int j=0; j<3; j++){
	    			  aux=obtenerOrigenSprite(matriz[42][j].nombre);
	    			  aux2=matriz[42][j].destino;
	    			  SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    		  }
	              //Dibujo: Felix 1
	    			aux=obtenerOrigenSprite(matriz[43][0].nombre);
	    			aux2=matriz[43][0].destino;
	    			SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);

	              //Dibujo: Felix 2
	    			aux=obtenerOrigenSprite(matriz[43][1].nombre);
	    			aux2=matriz[43][1].destino;
	    			SDL_BlitSurface(imagen2, &aux, pantallaBase, &aux2);

	    			//Dibujo: Los demas elementos: Ralph,Torta,Paloma,Ladrillos
	    			for(unsigned short int j=2; j<10; j++){
	    				if(matriz[43][j].nombre!=VACIO)
	    				  			{
	    			  aux=obtenerOrigenSprite(matriz[43][j].nombre);
	    			  aux2=matriz[43][j].destino;
	    			  SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    				  			}
	    		                }
	    			//Dibujo: Datos del panel superior Nombres,Puntajes,Rankings,Vidas,Nivel
	    			for(unsigned short int i=44; i<53; i++){
	    			  			for(unsigned short int j=0; j<10; j++){
	    			  				if(matriz[i][j].nombre!=VACIO)
	    			  				  			{
	    			  			  aux=obtenerOrigenSprite(matriz[i][j].nombre);
	    			  			  aux2=matriz[i][j].destino;
	    			  			  SDL_BlitSurface(imagen1, &aux, pantallaBase, &aux2);
	    			  				  			}
	    			  		                }
	    			 }

*/


	// Actualizo la superficie principal
	SDL_Flip(pantallaBase);

	//Actualizo toda la superficie
	SDL_UpdateRect(pantallaBase, 0, 0, 0, 0);

	/* Lo libero*/
	mutexPantalla->V();
	//TODO: Ver como queda esto.
}

/* Metodo que ejecuta las acciones iniciales de la partida y del display, antes de recibir acciones del servidor*/
void Partida::iniciarPartida(){
	instance->activo = CONST_TRUE;
	instance->stoped = CONST_TRUE;
	//TODO: Cosas basicas de administracion de la partida.
}

/* Acciones */

/* Metodo para la accion ACC_MOVER, y mover el objeto con id:id y en el sentido sentido que la accion lo indique. */
int Partida::move(t_accion *accion){
	//Obtengo la coordenada dentro de la matriz del elemento a mover
	SDL_Rect coordenada=idEntidadToXy(accion->id_entidad, instance->tramo);

	//Incremento la coordenada en x y la coordenada en y del elemento
    matriz[coordenada.x][coordenada.y].destino.x=accion->mov_x;
    matriz[coordenada.x][coordenada.y].destino.y=accion->mov_y;

   /* if(accion->id_entidad==ID_FELIX1 || accion->id_entidad==ID_FELIX2){

    	        int columnaFelix;//columna donde se guarda la posicion actual de Felix en la matriz
    	    	if(miIdJugador==ID_FELIX1)
    	    		columnaFelix=4;
    	    	else
    	    		columnaFelix=5;

    	    	int columnaVidrioFelix;
    	    	if(miIdJugador==ID_FELIX1)//columna donde se guarda el vidrio actual en el que esta Felix en la matriz
    	    		columnaVidrioFelix=7;
    	    	else
    	    		columnaVidrioFelix=8;

    	    	int columnaSpriteFelix;
    	    	if(miIdJugador==ID_FELIX1)//columna donde se guardan los datos del Sprite de Felix
    	    		columnaSpriteFelix=0;
    	    	else
    	    		columnaSpriteFelix=1;

    	if(accion->mov_x>0)//derecha
    	{
    	 matriz[42][columnaVidrioFelix].destino.x+= 1; //IDVidrio en el que esta Felix 1 dentro de la matriz
    	 matriz[42][columnaFelix].destino.x+= 2;//Columna donde esta Felix 1 en la matriz

         //Bajo la posicion en pantalla si estoy en la puerta
        if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 40)
          matriz[43][columnaSpriteFelix].destino.y= 419+30;
        else
          //Bajo la posicion en pantalla si estoy en la ventana central
        if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 37)
          matriz[43][columnaSpriteFelix].destino.y= 308+10;
        else
          matriz[43][columnaSpriteFelix].destino.y= 419-111*((5-tramo)*10+tramo-1-matriz[42][columnaFelix].destino.y)/3;

    	}
    	if(accion->mov_x<0)//izquierda
    	{
    	 matriz[42][columnaVidrioFelix].destino.x-= 1; //IDVidrio en el que esta Felix 1 dentro de la matriz
    	 matriz[42][columnaFelix].destino.x-= 2;//Columna donde esta Felix 1 en la matriz
         //Bajo la posicion en pantalla si estoy en la puerta
        if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 40)
          matriz[43][columnaSpriteFelix].destino.y= 419+30; //posicion en pantalla
        else
          //Bajo la posicion en pantalla si estoy en la ventana central
        if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 37)
          matriz[43][columnaSpriteFelix].destino.y= 308+10;
        else
          matriz[43][columnaSpriteFelix].destino.y= 419-111*((5-tramo)*10+tramo-1-matriz[42][columnaFelix].destino.y)/3;
    	}
    	if(accion->mov_y>0)//abajo
    	{
    	 matriz[42][columnaVidrioFelix].destino.x-= 10; //IDVidrio en el que esta Felix 1 dentro de la matriz
    	 matriz[42][columnaFelix].destino.y+= 3;//Fila donde esta Felix 1 en la matriz

    	 //Bajo la posicion en pantalla si estoy en la puerta
    	  if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 40)
    	     matriz[43][columnaSpriteFelix].destino.y= 419+30; //posicion en pantalla
    	  else
    	  //Bajo la posicion en pantalla si estoy en la ventana central
    	  if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 37)
    	    matriz[43][columnaSpriteFelix].destino.y= 308+10;
    	  else
    	    matriz[43][columnaSpriteFelix].destino.y= 419-111*((5-tramo)*10+tramo-1-matriz[42][columnaFelix].destino.y)/3;
    	}
    	if(accion->mov_y<0)//arriba
    	{
    	 matriz[42][columnaVidrioFelix].destino.x+= 10; //IDVidrio en el que esta Felix 1 dentro de la matriz
    	 matriz[42][columnaFelix].destino.y-= 3;//Fila donde esta Felix 1 en la matriz
    	 //Bajo la posicion en pantalla si estoy en la ventana central
    	 if(matriz[42][columnaFelix].destino.x== 4 && matriz[42][columnaFelix].destino.y== 37)
    	   matriz[43][columnaSpriteFelix].destino.y= 308+10;
    	 else
    	   matriz[43][columnaSpriteFelix].destino.y= 419-111*((5-tramo)*10+tramo-1-matriz[42][columnaFelix].destino.y)/3;

    	}
    }*/

	return CONST_UNO;
}

/* Metodo para eliminar un ave */
bool Partida::deleteAve(t_accion *action){
	matriz[43][6].nombre=VACIO;
	return CONST_TRUE;
}

/* Metodo para eliminar una torta */
bool Partida::deleteTorta(t_accion *action){
	//TODO:
	matriz[43][5].nombre=VACIO;
	return CONST_TRUE;
}

/* Metodo para eliminar un ladrillo */
bool Partida::deleteLadrillo(t_accion *action){
	//TODO:
	unsigned short int tramo=0;
	SDL_Rect coordenada=idEntidadToXy(action->id_entidad, tramo);
	//Borro campo nombre para que no se dibuje
	matriz[coordenada.x][coordenada.y].nombre=VACIO;
	return CONST_TRUE;
}

/* Metodo de reparacion de una ventana. */
bool Partida::reparar(t_accion *accion){
	//Obtengo la coordenada dentro de la matriz del vidrio a reparar
	SDL_Rect coordenada=idEntidadToXy(accion->id_entidad, tramo);

	//Reparo el elemento
	switch (matriz[coordenada.x][coordenada.y].nombre)
	{
	case VIDRIO_ROTO1:
		 matriz[coordenada.x][coordenada.y].nombre=VIDRIO_SANO;
		break;
	case VIDRIO_ROTO2:
		 matriz[coordenada.x][coordenada.y].nombre=VIDRIO_SANO;
		break;
	case VIDRIO_ROTO3:
		 matriz[coordenada.x][coordenada.y].nombre=VIDRIO_SANO;
		break;
	case VIDRIO_ROTO4:
		 matriz[coordenada.x][coordenada.y].nombre=VIDRIO_SANO;
		break;
	case VENT_CENT_ROTA:
		 matriz[coordenada.x][coordenada.y].nombre=VENT_CENT;
		break;
	case PUERTA_ROTA1:
		 matriz[coordenada.x][coordenada.y].nombre=PUERTA;
		break;
	case PUERTA_ROTA2:
		 matriz[coordenada.x][coordenada.y].nombre=PUERTA;
		break;
	case PUERTA_ROTA3:
		 matriz[coordenada.x][coordenada.y].nombre=PUERTA;
		break;
	}

	return CONST_TRUE;
}

/* Pasa al siguiente tramo */
bool Partida::finalizarTramo(t_accion *action){
	int scrollV=333;
	//Desplazo el dibujo verticalmente
	for(int i=0; i<=41;i++)
	  for(int j=0;j<=9;j++)
		 matriz[i][j].destino.y+=scrollV;

	 if(matriz[42][4].destino.y>14)
	  {
		 matriz[42][4].destino.y-= 9;
		 matriz[43][7].destino.y-= 111*3;
	  }
	 if(matriz[42][5].destino.y>14)
	  {
		 matriz[42][5].destino.y-= 9;
		 matriz[43][8].destino.y-= 111*3;
	  }
	return CONST_TRUE;
}

/* Pasa al siguiente nivel. */
bool Partida::finalizarNivel(t_accion *action){
	   unsigned int nivel=obtenerNivel();
	   nivel++;
	   matriz[52][0].nombre=obtenerIdNumero(nivel/10);//decenas
	   matriz[52][1].nombre=obtenerIdNumero(nivel%10);//unidades
	return CONST_TRUE;
}

/* Felix perdio las 3 vidas */
bool Partida::perderPartida(t_accion *action){

	 unsigned short int tramo=0;
	 SDL_Rect coordenada1=idEntidadToXy(action->id_entidad, tramo);
	 //Borro campo nombre para que no se dibuje
	 matriz[coordenada1.x][coordenada1.y].nombre=VACIO;
	 if(action->id_entidad==miIdJugador)
	   estoyVivo=false;

	return CONST_TRUE;
}

// Obtengo las vidas del jugador ////////////////////////////
unsigned char Partida::obtenerVidas(unsigned short int jugador)
{
unsigned char vidas;
if(jugador==JUGADOR1) //Jugador Local
{
  vidas=matriz[48][0].nombre;

}
else //Jugador Visitante
{
 vidas=matriz[49][0].nombre;
}
return vidas;
}

/* Felix pierde una vida */
bool Partida::restarVida(t_accion *action){

	unsigned char vidas;
		if(action->id_entidad==ID_FELIX1)
		{
			vidas=obtenerVidas(JUGADOR1);
			decrementarVidas(&vidas);
			cargarVidas(vidas,JUGADOR1);
		}
		else
		{
			vidas=obtenerVidas(JUGADOR2);
			decrementarVidas(&vidas);
			cargarVidas(vidas,JUGADOR2);
		}

	return CONST_TRUE;
}
// Decremento las vidas del jugador ///////////////////////////
void Partida::decrementarVidas(unsigned char *vidas)
{
*vidas=*vidas-1;
}

/* Termina la partida. */
bool Partida::finalizarPartida(t_accion *action){
	//TODO:
	return CONST_TRUE;
}

/* Ejecuta la accion de quitar a un jugador del juego y de la partida */
bool Partida::salirDelJuego(t_accion *action){
	//TODO:
	SDL_Quit();
	exit(1);
	return CONST_TRUE;
}

/* Metodo que interpreta la accion crear ave y activa un ave en la pos x,y indicada en la accion */
bool Partida::crearAve(t_accion *action){
	//Ubico la paloma en la posicion indicada en el mensaje
	matriz[43][6].destino.x=action->mov_x;
	matriz[43][6].destino.y=action->mov_y;
	matriz[43][6].nombre=PALOMA1;
	return CONST_TRUE;
}

/* Metodo que interpreta la accion crear ladrillo */
bool Partida::crearLadrillo(t_accion *action){

	 //Obtengo la coordenada dentro de la matriz del ladrillo a crear
	 unsigned short int tramo=0;
	 SDL_Rect coordenada=idEntidadToXy(action->id_entidad, tramo);
	 //Ubico el ladrillo en la posicion indicada en el mensaje
	 matriz[coordenada.x][coordenada.y].destino.x=action->mov_x;
	 matriz[coordenada.x][coordenada.y].destino.y=action->mov_y;
	 matriz[coordenada.x][coordenada.y].nombre=LADRILLO1;
	return CONST_TRUE;
}

/* Interpreta la accion crear ave */
bool Partida::crearTorta(t_accion *action){


	//Obtengo la coordenada dentro de la matriz del vidrio donde se creará la torta
	SDL_Rect coordenada=idEntidadToXy(action->id_entidad, tramo);
	//Ubico la torta sobre el vidrio indicado
	matriz[43][5].destino.x=matriz[coordenada.x][coordenada.y].destino.x;
	matriz[43][5].destino.y=matriz[coordenada.x][coordenada.y].destino.y-6;
	matriz[43][5].nombre=TORTA1;
	return CONST_TRUE;
}

/* Ejecuta la accion de lanzado de un ladrillo para ralph. */
bool Partida::lanzarLadrillo(t_accion *action){
	//TODO:


	return CONST_TRUE;
}

/* Ejecuta la accion de lanzado de un ladrillo para ralph. */
bool Partida::start(t_accion *action){
	instance->stoped = CONST_FALSE;
	instance->activo = CONST_TRUE;
	return CONST_TRUE;
}

/* Actualiza el puntaje de los jugadores */
bool Partida::actualizarPuntaje(t_accion *accion) {
	string puntaje;
	if(accion->id_entidad==ID_FELIX1){
		//puntaje=obtenerPuntaje(JUGADOR1);
		puntaje="0000000";
		incrementarPuntaje(&puntaje,accion->mov_x);
		cargarPuntaje(puntaje,JUGADOR1);
	}else{
		//puntaje=obtenerPuntaje(JUGADOR2);
		puntaje="0000000";
		incrementarPuntaje(&puntaje,accion->mov_x);
		cargarPuntaje(puntaje,JUGADOR2);
	}

	return CONST_TRUE;
}


/* Actualiza el ranking de los jugadores */
bool Partida::actualizarRanking(t_accion *accion) {
	if(accion->id_entidad==ID_FELIX1){
		//Ranking del 1 al 99
		matriz[50][0].nombre=obtenerIdNumero(accion->mov_x/10);//decenas
		matriz[50][0].destino.x=313;
		matriz[50][0].destino.y=60;
		matriz[50][1].nombre=obtenerIdNumero(accion->mov_x%10);//unidades
		matriz[50][1].destino.x=331;
		matriz[50][1].destino.y=60;
	}else{
		//Ranking del 1 al 99
		matriz[51][0].nombre=obtenerIdNumero(accion->mov_x/10);//decenas
		matriz[51][0].destino.x=508;
		matriz[51][0].destino.y=60;
		matriz[51][1].nombre=obtenerIdNumero(accion->mov_x%10);//unidades
		matriz[51][1].destino.x=526;
		matriz[51][1].destino.y=60;
	}

	return CONST_TRUE;
}

/* Inicia la partida en el juego */
bool Partida::inicializarPartida(t_accion *accion){
	/* Inicializa la matriz */
	instance->vaciarMatriz();

	/* Tomo el mutex */
	instance->mutexPantalla->P();

	//Obtengo que jugador soy, el 1 o el 2
	miIdJugador=accion->id_entidad;

	//Obtengo el nombre del otro jugador
	string nombreOtroJugador="";
	for (unsigned short int i=0;i<=10;i++)
		nombreOtroJugador+=accion->msj[i];

	//Corrijo el nombre del otro jugador: Solo letras y convertir a mayusculas
	nombreOtroJugador=corregirNombre(nombreOtroJugador);

	//Obtengo el nombre mio
	string nombreMio="";
	for (unsigned short int i=0;i<=instance->miNombre.length();i++)
	  nombreMio+=miNombre[i];

	//Corrijo mi nombre: Solo letras y convertir a mayusculas
	nombreMio=corregirNombre(nombreMio);

	if(miIdJugador==ID_FELIX1){ //Jugador Local
	  cargarNombre(nombreMio, JUGADOR1);
	  cargarNombre(nombreOtroJugador, JUGADOR2);
	}
	else{
	  cargarNombre(nombreMio, JUGADOR2);
	  cargarNombre(nombreOtroJugador, JUGADOR1);
	}

	/* Lo libero */
	instance->mutexPantalla->V();

	return CONST_TRUE;
}

/* Metodo que inicializa el nivel en la pantalla del jugador */
void Partida::inicializarNivel(t_accion *accion){

	/* Tomo el mutex */
	instance->mutexPantalla->P();

	//Niveles del 1 al 99
	matriz[52][0].nombre=obtenerIdNumero(accion->id_entidad/10);//decenas
	matriz[52][0].destino.x=382;matriz[52][0].destino.y=30;
	matriz[52][1].nombre=obtenerIdNumero(accion->id_entidad%10);//unidades
	matriz[52][1].destino.x=400;matriz[52][1].destino.y=30;

	int desde,sep;

	if(accion->id_entidad==1){//valores segun el numero de tramo en el que estoy
		desde=12;
		sep=-111;
	}else {
		desde=3;
		sep=-444;
	}

	int separacion=sep;

	//Posiciones en pantalla

	// Defino las posiciones de los Vidrios
	for(unsigned short int i=desde; i<=39;i+=3){
	    matriz[i][0].destino.x= 249; matriz[i][0].destino.y= -435+separacion; matriz[i][0].nombre=VIDRIO_SANO;
	    matriz[i+1][0].destino.x= 249; matriz[i+1][0].destino.y= -409+separacion; matriz[i+1][0].nombre=VIDRIO_SANO;
	    matriz[i][2].destino.x= 319; matriz[i][2].destino.y= -435+separacion; matriz[i][2].nombre=VIDRIO_SANO;
	    matriz[i+1][2].destino.x= 319; matriz[i+1][2].destino.y= -409+separacion; matriz[i+1][2].nombre=VIDRIO_SANO;
	    matriz[i][4].destino.x= 389; matriz[i][4].destino.y= -435+separacion; matriz[i][4].nombre=VIDRIO_SANO;
	    matriz[i+1][4].destino.x= 389; matriz[i+1][4].destino.y= -409+separacion; matriz[i+1][4].nombre=VIDRIO_SANO;
	    matriz[i][6].destino.x= 459; matriz[i][6].destino.y= -435+separacion; matriz[i][6].nombre=VIDRIO_SANO;
	    matriz[i+1][6].destino.x= 459; matriz[i+1][6].destino.y= -409+separacion; matriz[i+1][6].nombre=VIDRIO_SANO;
	    matriz[i][8].destino.x= 529; matriz[i][8].destino.y= -435+separacion; matriz[i][8].nombre=VIDRIO_SANO;
	    matriz[i+1][8].destino.x= 529; matriz[i+1][8].destino.y= -409+separacion; matriz[i+1][8].nombre=VIDRIO_SANO;
	    separacion+=111;
	}

	//Defino posicion de la puerta y la ventana central
	matriz[39][4].destino.x= 360; matriz[39][4].destino.y= 405;
	matriz[36][4].destino.x= 359; matriz[36][4].destino.y= 332;

	// Defino las posiciones de los bloqueos
	separacion=sep+111;
	for(unsigned short int i=(desde+3); i<=39;i+=3){

	   matriz[i-1][0].destino.x= 236; matriz[i-1][0].destino.y= -473+separacion;
	   matriz[i][1].destino.x= 280; matriz[i][1].destino.y= -448+separacion;

	   matriz[i-1][2].destino.x= 306; matriz[i-1][2].destino.y= -473+separacion;
	   matriz[i][3].destino.x= 350; matriz[i][3].destino.y= -448+separacion;

	   matriz[i-1][4].destino.x= 376; matriz[i-1][4].destino.y= -473+separacion;
	   matriz[i][5].destino.x= 420; matriz[i][5].destino.y= -448+separacion;

	   matriz[i-1][6].destino.x= 446; matriz[i-1][6].destino.y= -473+separacion;
	   matriz[i][7].destino.x= 490; matriz[i][7].destino.y= -448+separacion;

	   matriz[i-1][8].destino.x= 516; matriz[i-1][8].destino.y= -473+separacion;

	   separacion+=111;
	  }

	matriz[38][5].nombre=VACIO;
	matriz[41][5].nombre=VACIO;

	matriz[37][3].nombre=VACIO;
	matriz[36][5].nombre=VACIO;

	matriz[38][4].nombre=VACIO;
	matriz[40][3].nombre=VACIO;
	matriz[39][5].nombre=VACIO;

	matriz[40][4].nombre=BARRA_INF;
	matriz[40][4].destino.x= 109; matriz[40][4].destino.y=533;

	matriz[0][0].nombre=EDIF_AZOTEA;
	matriz[0][0].destino.x= 189; matriz[0][0].destino.y= -1216;

	matriz[0][1].nombre=EDIF_TRAMO;
	matriz[0][1].destino.x= 189; matriz[0][1].destino.y= -904;

	if(accion->id_entidad==1)
	{
	 matriz[0][0].destino.x= 189; matriz[0][0].destino.y= -883;
	 matriz[0][1].nombre=VACIO;
	}

	matriz[0][2].nombre=EDIF_TRAMO;
	matriz[0][2].destino.x= 189; matriz[0][2].destino.y= -571;

	matriz[0][3].nombre=EDIF_TRAMO;
	matriz[0][3].destino.x= 189; matriz[0][3].destino.y= -238;

	matriz[0][4].nombre=PASTO;
	matriz[0][4].destino.x= 109; matriz[0][4].destino.y= 508;

	matriz[0][5].nombre=EDIF_PLNT_BAJA;
	matriz[0][5].destino.x= 189; matriz[0][5].destino.y= 94;

	matriz[0][6].nombre=MACETA;
	matriz[0][6].destino.x= 253; matriz[0][6].destino.y= 502;

	matriz[0][7].nombre=MACETA;
	matriz[0][7].destino.x= 464; matriz[0][7].destino.y= 502;

	matriz[42][0].nombre=PANEL_SUP;
	matriz[42][0].destino.x= 0; matriz[42][0].destino.y= 0;

	matriz[42][1].nombre=BANDA_NEGRA;
	matriz[42][1].destino.x= 0; matriz[42][1].destino.y=537;

	matriz[42][2].nombre=BARRA_SUP;
	matriz[42][2].destino.x= 110; matriz[42][2].destino.y=86;

	matriz[42][3].nombre=BARRA_SUP;
	matriz[42][3].destino.x= 110; matriz[42][3].destino.y=80;

	//Posicion inicial de Felix 1 en la pantalla
	matriz[43][0].nombre=FELIX1;
	matriz[43][0].destino.x= 228; matriz[43][0].destino.y=419;

	//Posicion inicial de Felix 1 dentro de la matriz
	matriz[42][4].destino.x= 0; matriz[42][4].destino.y=40;

	//IDVidrio en el que esta Felix 1 dentro de la matriz
	matriz[42][7].destino.x= 0;

	//Posicion inicial de Felix 2 en la pantalla
	matriz[43][1].nombre=FELIX2;
	matriz[43][1].destino.x= 512; matriz[43][1].destino.y=419;

	//IDVidrio en el que esta Felix 2 dentro de la matriz
	matriz[42][8].destino.x= 4;

	//Posicion inicial de Felix 2 dentro de la matriz
	matriz[42][5].destino.x= 8; matriz[42][5].destino.y=40;

	//Posicion inicial de Ralph
	matriz[43][2].nombre=RALPH;
	matriz[43][2].destino.x= 228; matriz[43][2].destino.y=90;


	//Cargo puntaje inicial de los jugadores//////////////////////////
	string puntaje="0000000";
	cargarPuntaje(puntaje, JUGADOR1);

	puntaje="0000000";
	cargarPuntaje(puntaje, JUGADOR2);

	//Cargo vidas iniciales de los jugadores//////////////////////////
	unsigned char vidas=TRES;
	cargarVidas(vidas, JUGADOR1);
	cargarVidas(vidas, JUGADOR2);

	/* Lo libero */
	instance->mutexPantalla->V();
}

/* Inicializa el tramo en la pantalla de cliente sorteando los estados de vidrios y bloqueos */
void Partida::inicializarTramo(t_accion *accion){
	/* Tomo el mutex */
	instance->mutexPantalla->P();

	/* Genero el aleatorio*/
	srand(accion->mov_x);

	/* Dejamos en uno */
	accion->mov_y=1; 	//TODO: asdsa

	/* Sortea los vidrios y bloqueos */
	sortearVidrios(accion);
	sortearBloqueos(accion);

	/* Seteo el numero de tramo */
	instance->tramo = accion->id_entidad;

	/* Lo libero */
	instance->mutexPantalla->V();
}

//Sorteo estado de los vidrios en la matriz /////////////////////////////////////////
void Partida::sortearVidrios(t_accion *accion){
	SDL_Rect coordenada;

	//Comienzo recorriendo todos los vidrios
	for(unsigned short int idVidrio=ID_VIDRIO_INI; idVidrio<ID_VIDRIO_CANT; idVidrio++){
		/* Sorteo el estado. */
		char estado = (char)(rand()% CANT_ESTADOS_VIDRIO);

		/* Me posiciono en el vidrio seleccionado sobre la matriz. */
		coordenada=idEntidadToXy(idVidrio, accion->id_entidad);

		/* Modifico el estado */
		switch (estado){
		case 0:
		   matriz[coordenada.x][coordenada.y].nombre=VIDRIO_SANO;
		   break;
		case 1:
		   matriz[coordenada.x][coordenada.y].nombre=VIDRIO_ROTO1;
		   break;

		}
	}

	matriz[37][4].nombre=VACIO;
	matriz[40][4].nombre=VACIO;
	matriz[39][4].nombre=PUERTA;
	matriz[36][4].nombre=VENT_CENT;
}

//Cargo estado de los bloqueos en la matriz /////////////////////////////////////
void Partida::sortearBloqueos(t_accion *accion){
	    char estado;
	    SDL_Rect coordenada;

		//Defino el tipo de bloqueo a usar en este tramo, si por fila o por columna.
		char tipoBloqueo = (char)(rand()% CANT_TIPOS_BLOQ);
		//Ahora creo los bloqueos uno a uno
		for(short int idBloqueo=ID_BLOQUEO_INI; idBloqueo<=MAX_IDX_BLOQUEOS; idBloqueo++){
			//Sorteo el estado del bloqueo en proceso.
			estado = sortearEstadoBloqueo(idBloqueo, tipoBloqueo);

			//Si esta bloqueado es porque es un bloqueo activo.
			if(estado == ESTADO_BLOQ_LOCK){
				//Me posiciono en el bloqueo seleccionado sobre la matriz
				coordenada=idEntidadToXy(idBloqueo, accion->id_entidad);

				//Modifico el estado a activo
				 switch (tipoBloqueo){
					case TIPO_BLOQ_VERTI:
						matriz[coordenada.x][coordenada.y].nombre=BLOQ_ARR;
						   break;
					case TIPO_BLOQ_HORI:
						matriz[coordenada.x][coordenada.y].nombre=BLOQ_DER;
						   break;
				}
			}

			if(accion->id_entidad==CONST_UNO){ //Tramo 1
				   matriz[39][5].nombre=VACIO;
				   matriz[36][5].nombre=VACIO;
				   matriz[38][4].nombre=VACIO;
			}
		}

		//Ahora quito n bloqueos por fila o columna dependiendo del tipoBloqueo para que sea posible terminar el tramo.
		quitarBloqueosParaJugar(tipoBloqueo,accion);
}

/* Sortea el estado para cada bloqueo del tramo, uno a la vez. */
char Partida::sortearEstadoBloqueo(int i,char tipoBloqueo){
	//Tomo por defecto el estado libre.
	char estado = ESTADO_BLOQ_FREE;

	//Dependiendo del tipo de bloqueo aleatorio seleccionado veo si activo o no este bloqueo.
	if(tipoBloqueo == TIPO_BLOQ_VERTI){
		//Bloqueos por columna, solo bloquea los bloqueos verticales, identificados por el indice.
		if((i >= MIN_IDX_BLOQV_FILA1 && i<=MAX_IDX_BLOQV_FILA1) ||
		   (i >= MIN_IDX_BLOQV_FILA2 && i<=MAX_IDX_BLOQV_FILA2)   ){
			estado = ESTADO_BLOQ_LOCK;
		}
	}else{
		//Bloqueos por fila
		if((i >= MIN_IDX_BLOQH_FILA1 && i<=MAX_IDX_BLOQH_FILA1) ||
		   (i >= MIN_IDX_BLOQH_FILA2 && i<=MAX_IDX_BLOQH_FILA2) ||
		   (i >= MIN_IDX_BLOQH_FILA3 && i<=MAX_IDX_BLOQH_FILA3)   ){
			estado = ESTADO_BLOQ_LOCK;
		}
	};

	return estado;
}

/* Quita aleatoriamente la cantidad de bloqueos por fila o columna ingresada por parámetro. */
void Partida::quitarBloqueosParaJugar(char tipoBloqueo, t_accion *accion){
	//Voy a eliminar de a uno, la cantidad de bloqueos ingresada por parametro.
	for(int x=CONST_CERO; x <accion->mov_y; x++){
		//Me fijo si son bloqueos verticales u horizontales.
		if(tipoBloqueo == TIPO_BLOQ_VERTI)
			quitarBloqueoVertical(tipoBloqueo, accion);
		else
			quitarBloqueoHorizontal(tipoBloqueo, accion);
	}
}

/* Quita un bloqueo horizontal al azar. */
void Partida::quitarBloqueoHorizontal(char tipoBloqueo, t_accion *accion){
	SDL_Rect coordenada;

	//Por cada columna en la pantalla.
	for(short int col=CONST_CERO; col< CANT_COL_VENTANAS; col++){

		//Sorteo cual de los dos bloqueos por columna voy a liberar, si de fila 1 o fila 2
		short int filaALiberar = (rand() % CANT_BLOQ_X_COL);

		//Genero el id_entidad del bloqueo offseteando del minimo id para esta fila por offset que representa un salto de fila..
		int idBloqueo = ID_BLOQUEO_INI+col+filaALiberar*9;

		//Me posiciono en el bloqueo seleccionado sobre la matriz de elementos.
		coordenada=idEntidadToXy(idBloqueo,accion->id_entidad);

		//Modifico el estado a desactivado
		matriz[coordenada.x][coordenada.y].nombre=VACIO;
	}
}

/* Quita un bloqueo vertical al azar. */
void Partida::quitarBloqueoVertical(char tipoBloqueo, t_accion *accion){
	SDL_Rect coordenada;
	//Por cada fila de bloqueos verticales.
	for(short int fil=CONST_CERO; fil< CANT_FIL_VENTANAS; fil++){
		//Defino el idBase del cual offsetear por fila, para saber que bloqueo liberar.
		short int idBase = getIdBaseBloqueo(tipoBloqueo, fil);

		//Sorteo cual de los bloqueos voy a liberar, si de columna 1, columna 2, columna 3, columna 4 o columna 5
		short int columnaALiberar = (rand() % CANT_BLOQ_X_FIL);

		//Genero el id_entidad del bloqueo offseteando del minimo id para esta fila por offset que representa un salto de fila..
		int idBloqueo = idBase + columnaALiberar;

		//Me posiciono en el bloqueo seleccionado sobre la matriz de elementos.
		coordenada=idEntidadToXy(idBloqueo,accion->id_entidad);

		//Modifico el estado a desactivado
		matriz[coordenada.x][coordenada.y].nombre=VACIO;
	}
}

/* Trae los idEntidad base para offsetear y obtener los id de los bloqueos buscados. */
short int Partida::getIdBaseBloqueo(char tipoBloqueo, int fila) {
	//Veo si es bloqueo horizontal o vertical.
	if(tipoBloqueo == TIPO_BLOQ_HORI)
		switch(fila){
			case CONST_CERO:
				return MIN_IDX_BLOQH_FILA1;
				break;
			case CONST_UNO:
				return MIN_IDX_BLOQH_FILA2;
				break;
			case CONST_DOS:
				return MIN_IDX_BLOQH_FILA3;
				break;
			case CONST_TRES:
				return MIN_IDX_BLOQH_FILA2;
				break;
			case CONST_CUATRO:
				return MIN_IDX_BLOQH_FILA3;
				break;
		}
	else
		switch(fila){
			case CONST_CERO:
				return MIN_IDX_BLOQV_FILA1;
				break;
			case CONST_UNO:
				return MIN_IDX_BLOQV_FILA2;
				break;
		}
	return CONST_CERO;
}

/* COsas del display */
void Partida::vaciarMatriz(){
	/* Tomo el mutex */
	mutexPantalla->P();

	for(unsigned short int i=0; i<=52;i++)
	 for(unsigned short int j=0;j<=9;j++)
	  matriz[i][j].nombre=VACIO;

	/* Lo libero*/
	mutexPantalla->V();
}


// Cargo el nombre del Jugador en la matriz //////////////////////////
void Partida::cargarNombre(string nombre, unsigned short int jugador){
	unsigned short int letras=nombre.size();

	if(jugador==JUGADOR1){ //jugador1
	 for (unsigned short int j=0;j<letras;j++)
		 matriz[44][j].nombre=obtenerIdCaracter(1,nombre[j]);

	 for(unsigned short int j=0; j<=9;j+=1){
		 matriz[44][j].destino.x= 117+(220-letras*16+1)/2+16*j;
		 matriz[44][j].destino.y=10;
	 }
	}else {
	  for(unsigned short int j=0;j<letras;j++)
		 matriz[46][j].nombre=obtenerIdCaracter(2,nombre[j]);

	  for(unsigned short int j=0; j<=9;j+=1){
		 matriz[46][j].destino.x= 465+(220-letras*16+1)/2+16*j;
		 matriz[46][j].destino.y=10;
	  }
	}
}
